#ifndef OPENXMLVIEWER_XMLHELPER
#define OPENXMLVIEWER_XMLHELPER
#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

#include <iostream>
#include <map>
#include <utility>
#include <vector>
#include <sstream>
#include <string>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

#if defined(_WIN32) || defined(WIN32)
#include <windows.h>
#endif


using namespace std;
XERCES_CPP_NAMESPACE_USE

namespace Utility
{
	class WordXmlPicture
	{
	public:		
		WordXmlPicture();
		~WordXmlPicture();
		float width;
		bool widthSet;	
		float height;
		bool heightSet;
		XMLCh *targetFrame;
		XMLCh *tooltip;
		XMLCh *hlinkRef;
		XMLCh *alt;
		char *data; // data from w:bindata
		XMLCh *id; // id of image

		/*The attribute of the v:shape node which maps to the
		'style' attribute of and HTML 'img' tag.*/
		XMLCh* style;

		/*The attribute of the 'v:image' node in the Word
		Document which coresponds to the 'w:name' attribute of
		the 'w:bindata' node.*/
		XMLCh* src;

		/*The type of the picture as specified by the attribute of the v:shape node
		within the Word Document.*/
		XMLCh* type;

		static const int ExtentToPixelConversionFactor = 12700;

		void ReadStandardAttributes(DOMElement *fromNode);
		void ReadLinkAttributes(DOMElement *fromNode);
		void ReadSizeAttributes(DOMElement *fromNode);
		void SetWidth(int val);
		void SetHeight(int val);

	};

	class XMLHelper
	{		
	public:			

		//typedef std::map<const XMLCh*, const XMLCh*>Relationship_Map;	
		typedef std::vector<DOMElement*>XMLHelper_XPathResult;

		void XMLHelper::UpdateImageNames(map<const XMLCh*, const XMLCh*> &imgmap, string filename, const char*);
		void ReadRelationship(XercesDOMParser *parser, map<const XMLCh*, const XMLCh*> *rel_map, char *relationshipURI);	
		XMLCh* GetAttributeValue(const DOMNamedNodeMap *attr_list, char *id);
		XMLCh* GetAttributeValue(DOMElement* element, char *id);
		
		string GetFromAttributeValue(const DOMNamedNodeMap *attr_list, char *from);
		string GetToAttributeValue(const DOMNamedNodeMap *attr_list, char *to);

		XMLCh* GetServerRelativePath(XMLCh *docLibPath, XMLCh *itemUrl);
		void HandleImages(xercesc::DOMDocument *doc, map<const XMLCh*, const XMLCh*> imgMap, map<const XMLCh*, const XMLCh*> hyperlinkMap);
		void HandleNumberedLists(xercesc::DOMDocument *doc);
		void HandleThemeFonts(xercesc::DOMDocument *mainDoc);
		void HandleLinks(xercesc::DOMDocument *mainDoc, map<const XMLCh*, const XMLCh*> hyperlinkTable);
		void HandleColumns(xercesc::DOMDocument *mainDoc);
		void HandleTabIndentation(xercesc::DOMDocument *mainDoc);
		void HandleCoverPage(xercesc::DOMDocument *mainDoc);
		string getMsWordLanguageClassification(string textRun);		

		void PrintAttributes(const DOMNamedNodeMap *attr_list);

		vector<DOMElement*>* ParseMinimalXPath(xercesc::DOMDocument *doc, DOMElement *startNode, char *xpath);
		vector<DOMElement*>* GetXPathResults(xercesc::DOMDocument *doc, DOMNode *startNode, vector<string> tokens);
		DOMElement* SelectSingleNode(xercesc::DOMDocument *doc, DOMElement *selectNode, char *query);
		DOMElement* CreateImageElement(xercesc::DOMDocument *document, WordXmlPicture *picture, string fixupPath);

		char* LinkRelationshipUri;// = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
		char* ImageRelationshipUri;// = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";

		int convertToInt(const std::string& s);
		int convertToInt(const XMLCh* s);
		float convertToFloat(const std::string& s);
		float convertToFloat(const XMLCh* s);
		char* convertToString(const int i);
		string convertToString( float f);
		string convertToString(const XMLCh *s_xml);
		XMLCh* convertToXMLCh(const string s);
		XMLCh* convertToXMLCh(const int i);		
		void StrTokenize(string str, string delimiter, vector<string>*tokens);
		static XMLHelper* getInstance();		

	private:
		static XMLHelper *currentInstance;
		XMLHelper();
		~XMLHelper();
		void GetElements(vector<string>tokens, int depth, DOMTreeWalker *treewalker, XMLHelper::XMLHelper_XPathResult *selectedElements);
		vector<DOMElement*>* GetXPathResults(xercesc::DOMDocument *doc, DOMNode *startNode, char *query);

	};

	class ListLevel
	{
	public:
		XMLCh *id;
		XMLCh *levelText;
		XMLCh *font;
		int startValue;
		int counter;
		bool isBullet;

		void ResetCounter();
		void IncrementCounter();
		ListLevel(xercesc::DOMDocument *doc, DOMElement *levelNode);
		ListLevel();
		ListLevel(const ListLevel &masterCopy);
		void SetOverrides(xercesc::DOMDocument *doc, DOMElement *levelNode);
		void ListLevelIncrementCounter();

	};

	class AbstractListNumberingDefinition
	{
	public:
		map<XMLCh*, ListLevel> listLevels;
		XMLCh *linkedStyleId;
		XMLCh *abstractNumDefId;

		AbstractListNumberingDefinition();
		AbstractListNumberingDefinition(xercesc::DOMDocument *doc, DOMElement *abstractNumNode);
		void UpdateDefinitionFromLinkedStyle(xercesc::DOMDocument *doc, DOMElement *linkedNode);
		void readListLevelsFromAbsNode(xercesc::DOMDocument *doc, DOMElement *absNumNode);
	};

	class ListNumberingDefinition
	{
	public:
		AbstractListNumberingDefinition abstractListDefinition;
		map<XMLCh*, ListLevel> levels;
		XMLCh *listNumberId;

		ListNumberingDefinition();
		ListNumberingDefinition(xercesc::DOMDocument *doc, DOMElement *numNode, map<XMLCh*, AbstractListNumberingDefinition> abstractListDefinitions);
		void IncrementCounter(XMLCh *level);
		XMLCh* GetCurrentNumberString(XMLCh* level);
		XMLCh* GetFont(XMLCh *level);
		bool IsBullet(XMLCh *level);
		bool LevelExists(XMLCh *level);
	};
}

#endif